package com.cavy.platform.server.repository.impl;

import com.cavy.platform.server.ResultList;
import com.cavy.platform.server.domain.Plugin;
import com.cavy.platform.server.domain.PluginRepositorySetting;
import com.cavy.platform.server.dto.PluginSearchDto;
import com.cavy.platform.server.repository.PluginRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 插件仓储库
 */
@Repository
public class PluginRepositoryImpl implements PluginRepository {
    public static final String DESCRIPTION_FILE_NAME = "Description.md";
    public static final String OBJECT_FILE_NAME = "info.json";
    public static final String LOGO_FILE_NAME = "logo";
    @Value("${cavy.plugin.dir}")
    private String pluginDir;

    private List<PluginRepository> repositoryList;
    private LocalPluginRepositoryImpl localPluginRepository;
    @Autowired
    private PluginRepositorySettingRepositoryImpl settingRepository;

    //1,加载所有的仓库地址
    //2,实例所有仓库repository
    @PostConstruct
    private void init() {
        List<PluginRepositorySetting> list = settingRepository.getList();
        initRepository(list);
    }

    private void initRepository(List<PluginRepositorySetting> list) {
        repositoryList = new ArrayList<>(list.size());
        for (PluginRepositorySetting setting : list) {
            if (setting.isLocal()) {
                localPluginRepository = new LocalPluginRepositoryImpl(pluginDir + File.separator + setting.getCode(), setting);
                repositoryList.add(localPluginRepository);
            } else {
                repositoryList.add(new RemotePluginRepositoryImpl(pluginDir + File.separator + setting.getCode(), setting));
            }
        }
    }

    @Override
    public long countByName(String name, String version) {
        for (PluginRepository pluginRepository : repositoryList) {
            if (pluginRepository.countByName(name, version) > 0) {
                return 1;
            }
        }
        return 0;
    }

    @Override
    public void create(Plugin plugin) throws IOException {
        localPluginRepository.create(plugin);
    }

    @Override
    public void delete(String name, String version) {
        localPluginRepository.delete(name, version);
    }

    @Override
    public ResultList list(PluginSearchDto dto) {
        List<String> result = new ArrayList<>();
        for (PluginRepository pluginRepository : repositoryList) {
            String[] files = pluginRepository.listByDto(dto);
            if (files == null || files.length == 0) {
                continue;
            }
            result.addAll(Arrays.asList(files));
        }
        List<String> list = new ArrayList<>();
        ResultList info = new ResultList();
        if (!result.isEmpty()) {
            int length = result.size();
            for (int i = getStartIndex(dto.getCurrent(), dto.getSize(), length); i < getEndIndex(dto.getCurrent(), dto.getSize(), length); i++) {
                list.add(result.get(i));
            }
            info.setTotalPage(getTotalPage(dto.getSize(), length));
        }
        info.setCurrentPage(dto.getCurrent());
        info.setData(list);
        return info;
    }

    @Override
    public String[] listByDto(PluginSearchDto dto) {
        throw new UnsupportedOperationException("不支持的操作");
    }

    @Override
    public String[] getVersionList(String name) {
        for (PluginRepository pluginRepository : repositoryList) {
            String[] versionList = pluginRepository.getVersionList(name);
            if (versionList != null && versionList.length > 0) {
                return versionList;
            }
        }
        throw new RuntimeException("未在仓库中找到插件:" + name + "对应的版本信息");
    }

    @Override
    public Plugin info(String name, String version) throws IOException {
        for (PluginRepository pluginRepository : repositoryList) {
            Plugin info = pluginRepository.info(name, version);
            if (info != null) {
                return info;
            }
        }
        return null;
    }

    @Override
    public File getLogo(String name, String lastVersion) {
        for (PluginRepository pluginRepository : repositoryList) {
            File logo = pluginRepository.getLogo(name, lastVersion);
            if (logo != null && logo.exists()) {
                return logo;
            }
        }
        return null;
    }

    @Override
    public void deleteInfo(String name, String version) {
        localPluginRepository.delete(name, version);
    }

    @Override
    public void refresh() {
        settingRepository.refresh();
        initRepository(settingRepository.getList());
        for (PluginRepository pluginRepository : repositoryList) {
            pluginRepository.refresh();
        }
    }

    @Override
    public void saveLogo(String name, String version, MultipartFile file) {
        localPluginRepository.saveLogo(name, version, file);
    }

    private int getTotalPage(int pageSize, int length) {
        int i = length / pageSize;
        if (length % pageSize > 0) {
            return i + 1;
        }
        return i;
    }

    private int getEndIndex(int page, int pageSize, int length) {
        if (page <= 0) {
            return pageSize > length ? length : pageSize;
        }
        int temp = page * pageSize;
        return temp > length ? length : temp;
    }

    private int getStartIndex(int page, int pageSize, int length) {
        if (page < 0) {
            return 0;
        }
        int temp = (page - 1) * pageSize;
        return temp > length ? length : temp;
    }
}
